﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing; 
 
using DevelopAssistant.Service.Properties;
using DevelopAssistant.Service;
using ICSharpCode.TextEditor;

namespace DevelopAssistant.Service.MSQLIntellisense
{
    public class SqlIntellisenseBox : IntellisenseBox
    {
        private readonly ImageList images;

        bool fixedListViewWidth = false;//是否固定大小

        IList<SqlIntellisenseBoxItem> IntellisenseList = null;

        SqlIntellisense Intellisense = null;

        TextArea ActiveTextArea = null;

        public SqlIntellisenseBox(SqlIntellisense intellisense, TextArea textArea)
        {
            this.Intellisense = intellisense;

            this.images = new ImageList();
            this.images.Images.Add("Keyword", (Image)Resources.star);         
            this.images.Images.Add("Table", (Image)Resources.table);
            this.images.Images.Add("View", (Image)Resources.view);
            this.images.Images.Add("Column", (Image)Resources.column);
            this.images.Images.Add("Proc", (Image)Resources.procs);
            this.images.Images.Add("Function", (Image)Resources.func);
            this.images.Images.Add("Variable", (Image)Resources.var);
            this.images.Images.Add("Snippet", (Image)Resources.snippets);

            this.ImageList = this.images;
            this.ActiveTextArea = textArea;

            this.VScrollBar.DisabledProcessDialogKey = true;
            this.VScrollBar.SmallChange = this.ItemHeight;
            this.VScrollBar.LargeChange = MaxListLength;
            this.VScrollBar.ValueChanged += VScrollBar_ValueChanged;

            this.HScrollBar.DisabledProcessDialogKey = true;
        }

        private void VScrollBar_ValueChanged(object sender, EventArgs e)
        {
            VisiableTop = new Point(0, -this.VScrollBar.Value * ItemHeight);
        }

        public override bool DoWithPromptBox(KeyEventArgs key)
        {
            int _selectedIndex = this.SelectedIndex;
            switch (key.KeyData)
            {
                case Keys.End:
                    _selectedIndex = this.Items.Count - 1;
                    if (VScrollBar.Visible)
                    {
                        VScrollBar.Value = VScrollBar.Maximum;
                    }
                    SelectedIndex = _selectedIndex;
                    return false;
                case Keys.Home:
                    _selectedIndex = 0;
                    if (VScrollBar.Visible)
                    {
                        VScrollBar.Value = 0;
                    }
                    this.SelectedIndex = _selectedIndex;
                    return false;
                case Keys.Up:
                    if (_selectedIndex > 0)
                    {
                        _selectedIndex -= 1;
                        if (VScrollBar.Visible)
                        {
                            if (this.IntellisenseList[_selectedIndex].Bounds.Top < 0 ||
                                this.IntellisenseList[_selectedIndex].Bounds.Top > this.Height - DefaultPadding.Top - DefaultPadding.Bottom)
                            {
                                this.VScrollBar.Value -= 1;
                            }
                        }                        
                    }                   
                    else
                    {
                        _selectedIndex = this.Items.Count - 1;
                        if (VScrollBar.Visible)
                        {
                            VScrollBar.Value = VScrollBar.Maximum;
                        }
                    }
                    this.SelectedIndex = _selectedIndex;
                    return false;
                case Keys.Down:
                    if (_selectedIndex < this.Items.Count - 1)
                    {
                        _selectedIndex += 1;
                        if (VScrollBar.Visible)
                        {
                            if (this.IntellisenseList[_selectedIndex].Bounds.Top < 0 ||
                                this.IntellisenseList[_selectedIndex].Bounds.Top > this.Height - DefaultPadding.Top - DefaultPadding.Bottom)
                            {
                                VScrollBar.Value += 1;
                            }
                        }
                    }
                    else
                    {
                        _selectedIndex = 0;
                        if (VScrollBar.Visible)
                        {
                            VScrollBar.Value = _selectedIndex;
                        }
                    }
                    this.SelectedIndex = _selectedIndex;
                    return false;
                case Keys.Enter:
                    if (Intellisense != null)
                    {
                        Intellisense.SetCompleteText();
                    }
                    return false;                    
                default:
                    return true;
            }
        }

        protected override bool DoProcessDialogKey(Keys keyData)
        {
            return DoWithPromptBox(new KeyEventArgs(keyData));
        }

        public ImageList GetImageList()
        {
            return images;
        }

        public int GetImageIndex(SqlPromptType type)
        {
            switch (type)
            {
                case SqlPromptType.Procedure:
                    return 4;
                case SqlPromptType.UserFunction:
                case SqlPromptType.SysFunction:
                    return 5;
                case SqlPromptType.Variables:
                    return 6;
                case SqlPromptType.Table:
                    return 1;
                case SqlPromptType.Column:
                    return 3;
                case SqlPromptType.View:
                    return 2;
                case SqlPromptType.Snippet:
                    return 7;
                case SqlPromptType.Keyword:
                    return 0;                
                default:
                    return 0;
            }
        }

        public void FilterItems(string key, IList<SqlIntellisenseBoxItem> IntellisenseBoxItems)
        {
            int num = 0;
            this.Items.Clear();
            if (IntellisenseBoxItems == null)
                return;
            if (key.Contains("."))
                key = key.Substring(key.IndexOf('.') + 1);
            key = key.ToLower();           
            List<SqlIntellisenseBoxItem> _list = new List<SqlIntellisenseBoxItem>();
            foreach (SqlIntellisenseBoxItem intellisenseBoxItem in (IEnumerable<SqlIntellisenseBoxItem>)IntellisenseBoxItems)
            {
                if (intellisenseBoxItem.Text.ToLower().StartsWith(key))
                {
                    _list.Add(intellisenseBoxItem);
                    this.Items.Add((object)intellisenseBoxItem);
                    ++num;
                }
            }

            this.IntellisenseList = _list;
            this.AdjustSize();          
        }

        public void AdjustSize()
        {
            //VisiableTop = new Point(0, 0);
            VScrollBar.Value = 0;
            int width = this.ItemHeight * 10;
            int height = this.ItemHeight * Math.Min(MaxListLength, IntellisenseList.Count); 
            if (!fixedListViewWidth)
            {
                if (ActiveTextArea != null && ActiveTextArea.Height < height)
                {
                    MaxListLength = Math.Max(ActiveTextArea.Height / ItemHeight / 2, 1);
                    height = Math.Min(this.ItemHeight * MaxListLength, height);
                }
                width = GetListViewWidth(width, height);
            }           
            width = width + DefaultPadding.Left + DefaultPadding.Right;
            height = height + DefaultPadding.Top + DefaultPadding.Bottom; //Padding (2,2,2,2)
            Size = new Size(width, height);
        }

        int GetListViewWidth(int defaultWidth, int height)
        {
            float width = defaultWidth;
            using (Graphics graphics = this.CreateGraphics())
            {
                for (int i = 0; i < IntellisenseList.Count; ++i)
                {
                    float itemWidth = graphics.MeasureString(IntellisenseList[i].Text.ToString(), this.Font).Width;
                    if (itemWidth > width)
                    {
                        width = itemWidth;
                    }
                }
            }

            int totalItemsHeight = this.ItemHeight * IntellisenseList.Count;
            if (totalItemsHeight > height)
            {
                width += ScrollBarInformation.VerticalScrollBarWidth; // Compensate for scroll bar.
                this.VScrollBar.SmallChange = 1;
                this.VScrollBar.LargeChange = MaxListLength;
                this.VScrollBar.Maximum = IntellisenseList.Count - MaxListLength;                 
                this.VScrollBar.SetBounds((int)width + DefaultPadding.Left + DefaultPadding.Right - ICSharpCode.WinFormsUI.Controls.ScrollBarInformation.VerticalScrollBarWidth - 1, DefaultPadding.Top,
                       ScrollBarInformation.VerticalScrollBarWidth, height);

                if (!this.VScrollBar.Visible)
                    this.VScrollBar.Visible = true;
            }
            else
            {
                if (!this.VScrollBar.Visible)
                    this.VScrollBar.Visible = false;
            }

            return (int)width;

        }

        private static SqlIntellisenseBox IntellisenseBox = null;
        private static object lockobject = new object();

        public static SqlIntellisenseBox Instance
        {
            get
            {
                if (IntellisenseBox == null)
                {
                    lock (lockobject)
                    {
                        if (IntellisenseBox == null)
                        {
                            IntellisenseBox = new SqlIntellisenseBox(null, null);
                        }
                    }                     
                }
                return IntellisenseBox;
            }
        }
    }
}
